#include<iostream>
#include<map>
#include<string>
#include<mutex>
using namespace std;
//class HeapOnly
//{
//public:
//	static HeapOnly* CreateObject()
//	{
//		return new HeapOnly;
//	}
//private:
//	HeapOnly() {}
//	HeapOnly(const HeapOnly&) = delete;
//};
//
//int main()
//{
//	//HeapOnly hp1;
//	HeapOnly* php2 = HeapOnly::CreateObject();
//	//static HeapOnly hp3;
//	return 0;
//}


//class HeapOnly
//{
//public:
//	HeapOnly()
//	{}
//	void Destory()
//	{
//		this->~HeapOnly();
//	}
//private:
//	~HeapOnly()
//	{}
//
//	HeapOnly(const HeapOnly&) = delete;
//};
//
//int main()
//{
//	HeapOnly* php1 = new HeapOnly;
//	php1->Destory();
//
//	return 0;
//}

//请设计一个类，只能在栈上创建对象
//class StackOnly
//{
//public:
//	static StackOnly&& CreateObj()
//	{
//		return StackOnly();
//	}
//	/*void* operator new(size_t size) = delete;
//	void operator delete(void* p) = delete;*/
//
//	void Print() const
//	{
//		cout << "StackOnly::Print()" << endl;
//	}
//private:
//	StackOnly()
//	{}
//	StackOnly(const StackOnly&) = delete;
//
//};
//int main()
//{
//	/*StackOnly so1 = StackOnly::CreateObj();
//	static StackOnly so2 = StackOnly::CreateObj();*/
//
//	StackOnly::CreateObj().Print();
//	const StackOnly& so4 = StackOnly::CreateObj();
//	so4.Print();
//	return 0;
//}




//int main()
//{
//	StackOnly so1 = StackOnly::CreateObj();
//	 下面两种静态区和堆的位置都不能创建
//	static StackOnly so2;
//	StackOnly* pso3 = new StackOnly;
//	return 0;
//}


//单例模式的类：全局只有一个唯一对象
// 饿汉模式（main函数之前初始化）
// 缺点：1、单例对象初始化时对象太多，导致启动慢 
//		 2、多个单例类有初始化依赖关系，饿汉模式无法控制
//class InfoSingleton
//{
//public:
//	static InfoSingleton& GetInstance()
//	{
//		return _sins;
//	}
//
//	void Insert(string name, int salary)
//	{
//		_info[name] = salary;
//	}
//
//	void Print()
//	{
//		for (auto kv : _info)
//		{
//			cout << kv.first << ":" << kv.second << endl;
//		}
//	}
//private:
//	InfoSingleton()
//	{}
//	InfoSingleton(const InfoSingleton&) = delete;
//	InfoSingleton& operator=(const InfoSingleton& info) = delete;
//	map<string, int> _info;
//	// ...
//private:
//	static InfoSingleton _sins;
//};
//
//InfoSingleton InfoSingleton::_sins;
//
//int main()
//{
//	InfoSingleton::GetInstance().Insert("张三", 10000);
//	InfoSingleton& infosl = InfoSingleton::GetInstance();
//	infosl.Insert("李四", 12000);
//	infosl.Insert("王五", 15000);
//	infosl.Insert("赵六", 11000);
//
//	infosl.Print();
//	cout << endl;
//	InfoSingleton::GetInstance().Insert("张三", 18000);
//	infosl.Insert("李四", 12000);
//	infosl.Insert("王五", 15000);
//	infosl.Insert("赵六", 11000);
//	infosl.Print();
//	return 0;
//}


//RAII的锁管理类
template<class Lock>
class LockGuard
{
public:
	LockGuard(Lock& lk)
		:_lk(lk)
	{
		lk.lock();
	}

	~LockGuard()
	{
		_lk.unlock();
	}
private:
	Lock& _lk;//成员变量用引用-->避免拷贝
};

//懒汉模式
//1、对象在main函数之后才会创建，不会影响启动顺序
//2、可以主动控制创建顺序
//class InfoSingleton
//{
//public:
//	//多个对象一起调用GetInstance，存在线程安全的风险，可能new出来多个对象，因此需要加锁
//	static InfoSingleton& GetInstance()
//	{
//		//第一次获取单例对象的时候创建对象
//		//双检查加锁
//		if (_psins == nullptr)//避免对象new出来以后每次都加锁，提高性能
//		{
//			// t1  t2
//			//LockGuard<mutex> mtx(_smtx);
//			std::lock_guard<mutex> lock(_smtx);
//			if (_psins == nullptr) //保证线程安全且只new一次
//			{
//				_psins = new InfoSingleton;
//			}
//		}
//
//		return *_psins;
//	}
//
//	//一般单例对象不需要考虑释放
//	//单例对象不用时，必须手动处理，一些资源需要保存
//	static void DelInstance()
//	{
//		//保存数据到文件
//		// ...
//		std::lock_guard<mutex> lock(_smtx);
//		if (_psins)
//		{
//			delete _psins;
//			_psins = nullptr;
//		}
//	}
//	//忘记调用DelInstance()，自动回收
//	class GC
//	{
//	public:
//		~GC()
//		{
//			if (_psins)
//			{
//				cout << " ~GC()" << endl;
//				DelInstance();
//			}
//		}
//	};
//
//	void Insert(string name, int salary)
//	{
//		_info[name] = salary;
//	}
//
//	void Print()
//	{
//		for (auto kv : _info)
//		{
//			cout << kv.first << ":" << kv.second << endl;
//		}
//	}
//private:
//	InfoSingleton()
//	{}
//	InfoSingleton(const InfoSingleton&) = delete;
//	InfoSingleton& operator=(const InfoSingleton& info) = delete;
//	map<string, int> _info;
//	// ...
//private:
//	static InfoSingleton* _psins;
//	static mutex _smtx;
//	static GC _gc;
//};
//
//InfoSingleton* InfoSingleton::_psins = nullptr;
//mutex InfoSingleton::_smtx;
//InfoSingleton::GC InfoSingleton::_gc;
//
//int main()
//{
//	InfoSingleton::GetInstance().Insert("张三", 10000);
//	InfoSingleton& infosl = InfoSingleton::GetInstance();
//	infosl.Insert("李四", 12000);
//	infosl.Insert("王五", 15000);
//	infosl.Insert("赵六", 11000);
//
//	infosl.Print();
//	cout << endl;
//	InfoSingleton::GetInstance().Insert("张三", 18000);
//	infosl.Insert("李四", 12000);
//	infosl.Insert("王五", 15000);
//	infosl.Insert("赵六", 11000);
//	infosl.Print();
//	return 0;
//}

//是懒汉：因为静态的局部变量是在main函数之后才创建初始化的：局部静态变量的初始化只初始化一次。
//C++11之前，不能保证sinst的初始化是线程安全的。
//C++11之后，可以。
class InfoSingleton
{
public:
	//多个对象一起调用GetInstance，存在线程安全的风险，可能new出来多个对象，因此需要加锁
	static InfoSingleton& GetInstance()
	{
		static InfoSingleton sinst;
		return sinst;
	}


	void Insert(string name, int salary)
	{
		_info[name] = salary;
	}

	void Print()
	{
		for (auto kv : _info)
		{
			cout << kv.first << ":" << kv.second << endl;
		}
	}
private:
	InfoSingleton()
	{
		cout << "InfoSingleton()" << endl;
	}
	InfoSingleton(const InfoSingleton&) = delete;
	InfoSingleton& operator=(const InfoSingleton& info) = delete;
	map<string, int> _info;
	// ...
private:
};

int main()
{
	InfoSingleton::GetInstance().Insert("张三", 10000);
	InfoSingleton& infosl = InfoSingleton::GetInstance();
	infosl.Insert("李四", 12000);
	infosl.Insert("王五", 15000);
	infosl.Insert("赵六", 11000);

	infosl.Print();
	cout << endl;
	InfoSingleton::GetInstance().Insert("张三", 18000);
	infosl.Insert("李四", 12000);
	infosl.Insert("王五", 15000);
	infosl.Insert("赵六", 11000);
	infosl.Print();
	return 0;
}